package br.unipar.academico;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRMapCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;

public abstract class AbstractReportManager<T> {

    private static Map<String, JasperReport> jrCache = new HashMap<String, JasperReport>();

    private JasperPrint createReport(String rn, List<Map<String, Object>> values) {
        return createReport(rn, new HashMap<String, Object>(), values);
    }

    private JasperPrint createReport(String rn, Map<String, Object> parameters,
            List<Map<String, Object>> values) {
        JasperReport jr = jrCache.get(rn);

        if (jr == null) {
            InputStream is = AbstractReportManager.class.getResourceAsStream(rn);

            if (is == null) {
                throw new IllegalArgumentException(
                        "Não foi possível localizar o relatório. " + rn);
            } else {
                try {
                    jr = (JasperReport) JRLoader.loadObject(is);
                } catch (JRException e) {
                    throw new IllegalArgumentException(
                            "Erro ao carregar relatório. " + rn);
                }
                jrCache.put(rn, jr);
            }
        }

        try {
            return JasperFillManager.fillReport(jr, parameters,
                    new JRMapCollectionDataSource(values));
        } catch (JRException e) {
            throw new IllegalArgumentException(
                    "Erro ao preencher o relatorio. " + rn);
        }
    }

    private JasperPrint createJasperPrint(List<T> list, String rn) {
        List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();

        for (T bean : list) {
            values.add(createValues(bean));
        }

        JasperPrint jp = new JasperPrint();
        jp.setPageHeight(820);
        jp.setPageWidth(590);

        if (values.size() > 0) {
            jp.getPages().addAll(createReport(rn, values).getPages());
        }

        return jp;

    }

    public void visualizar(List<T> list, String rn, String filename) {
        try {
            JasperPrint jasperPrint = createJasperPrint(list, rn);

            FacesContext facesContext = FacesContext.getCurrentInstance();
            HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", String.format("inline;filename=%s.pdf", filename));
            JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
            facesContext.responseComplete();
        } catch (JRException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public abstract Map<String, Object> createValues(T bean);
}
